home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / aminet / util / edit / jed207.lha / src / jed.lha / find.c < prev    next >
C/C++ Source or Header  |  1993-01-16  |  9KB  |  464 lines

  1.  
  2. /*
  3.  * FIND.C
  4.  * (c) 1993 J.Harper
  5.  */
  6.  
  7. #include "jed.h"
  8. #include "jed_protos.h"
  9.  
  10. Prototype   VALUE * cmd_find        (LONG, VALUE *);
  11. Prototype   VALUE * cmd_replace        (LONG, VALUE *);
  12. Prototype   BOOL    findcol0        (STRPTR);
  13.  
  14. Local UBYTE SearchBuff[100];
  15. Local UBYTE ReplaceBuff[100];
  16. Local BOOL  WildSearch;
  17. Local BOOL  CaseSearch;
  18.  
  19. #ifndef NOREGEXP
  20. Local BOOL  RESearch;
  21. Local BOOL  findREprev(VOID);
  22. Local BOOL  replaceitRE(VOID);
  23. Local BOOL  findREnext(VOID);
  24. #endif
  25.  
  26. Local BOOL  findnext(VOID);
  27. Local BOOL  findprev(VOID);
  28. Local BOOL  replaceit(VOID);
  29. Local BOOL  mystrcmp(STRPTR, STRPTR);
  30. Local BOOL  mystricmp(STRPTR, STRPTR);
  31.  
  32. /*
  33.  * (find `s' searchstring)
  34.  * (find `w' bool)
  35.  * (find `c' bool)
  36.  * (find `n')
  37.  * (find `p')
  38.  * (find `r' bool)
  39.  */
  40. VALUE *
  41. cmd_find(LONG argc, VALUE *argv)
  42. {
  43.     if(TPLATE2(VTF_STRING, VTF_ANY))
  44.     {
  45.     switch(*(ARG1.val_Value.String))
  46.     {
  47.         case 's':
  48.         if(ARG2.val_Type == VTF_STRING)
  49.         {
  50.             strncpy(SearchBuff, ARG2.val_Value.String, 99);
  51.             setnumres(TRUE);
  52.         }
  53.         else
  54.             settitle("syntax error: argument 2 should be a string");
  55.         break;
  56.         case 'w':
  57.         WildSearch = ARG2.val_Value.Number;
  58.         setnumres(TRUE);
  59.         break;
  60.         case 'c':
  61.         CaseSearch = ARG2.val_Value.Number;
  62.         setnumres(TRUE);
  63.         break;
  64.         case 'n':
  65. #ifndef NOREGEXP
  66.         setnumres(RESearch ? findREnext() : findnext());
  67. #else
  68.         setnumres(findnext());
  69. #endif
  70.         resyncxy();
  71.         break;
  72.         case 'p':
  73. #ifndef NOREGEXP
  74.         setnumres(RESearch ? findREprev() : findprev());
  75. #else
  76.         setnumres(findprev());
  77. #endif
  78.         resyncxy();
  79.         break;
  80. #ifndef NOREGEXP
  81.         case 'r':
  82.         RESearch = ARG2.val_Value.Number;
  83.         setnumres(TRUE);
  84.         break;
  85. #endif
  86.         default:
  87.         settitlefmt("error: incorrect find argument %s", (LONG)ARG1.val_Value.String);
  88.         break;
  89.     }
  90.     }
  91.     return(&RES);
  92. }
  93.  
  94. /*
  95.  * (replace `s' repstring)
  96.  * (replace `r')
  97.  */
  98. VALUE *
  99. cmd_replace(LONG argc, VALUE *argv)
  100. {
  101.     if(TPLATE2(VTF_STRING, VTF_ANY))
  102.     {
  103.     switch(*(ARG1.val_Value.String))
  104.     {
  105.         case 's':
  106.         if(ARG2.val_Type == VTF_STRING)
  107.         {
  108.             strncpy(ReplaceBuff, ARG2.val_Value.String, 99);
  109.             setnumres(TRUE);
  110.         }
  111.         else
  112.             settitle("syntax error: argument 2 should be a string");
  113.         break;
  114.         case 'r':
  115.         if(padcursor()) /* primarily to update undo-buffer */
  116.         {
  117. #ifndef NOREGEXP
  118.             setnumres(RESearch ? replaceitRE() : replaceit());
  119. #else
  120.             setnumres(replaceit());
  121. #endif
  122.             resyncxy();
  123.         }
  124.         else
  125.             setnumres(FALSE);
  126.         break;
  127.     }
  128.     }
  129.     return(&RES);
  130. }
  131.  
  132. Local BOOL
  133. findnext(VOID)
  134. {
  135.     UBYTE parsed[202];
  136.     STRPTR find;
  137.     VW *vw = CurrVW;
  138.     LONG linenum = vw->vw_CursorPos.pos_Line;
  139.     LINE *line = vw->vw_Tx->tx_Lines + linenum;
  140.     LONG i = vw->vw_CursorPos.pos_Col + 1;
  141.     LONG (*cmpfunc)(STRPTR, STRPTR);
  142.  
  143.     if(WildSearch)
  144.     {
  145.     LONG prc;
  146.     if(CaseSearch)
  147.     {
  148.         prc = ParsePattern(SearchBuff, parsed, 202);
  149.         cmpfunc = MatchPattern;
  150.     }
  151.     else
  152.     {
  153.         prc = ParsePatternNoCase(SearchBuff, parsed, 202);
  154.         cmpfunc = MatchPatternNoCase;
  155.     }
  156.     if(prc < 0)
  157.     {
  158.         settitle("error: can't parse pattern for wildcard search");
  159.         return(FALSE);
  160.     }
  161.     find = parsed;
  162.     }
  163.     else
  164.     {
  165.     find = SearchBuff;
  166.     cmpfunc = CaseSearch ? mystrcmp : mystricmp;
  167.     }
  168.     while(linenum < vw->vw_Tx->tx_NumLines)
  169.     {
  170.     while(i < line->ln_Strlen)
  171.     {
  172.         if(cmpfunc(find, line->ln_Line + i))
  173.         {
  174.         setautomark();
  175.         vw->vw_CursorPos.pos_Col = i;
  176.         vw->vw_CursorPos.pos_Line = linenum;
  177.         return(TRUE);
  178.         }
  179.         i++;
  180.     }
  181.     line++;
  182.     linenum++;
  183.     i = 0;
  184.     }
  185.     settitlefmt("can't find %s", (LONG)SearchBuff);
  186.     return(FALSE);
  187. }
  188.  
  189. Local BOOL
  190. findprev(VOID)
  191. {
  192.     UBYTE parsed[202];
  193.     STRPTR find;
  194.     VW *vw = CurrVW;
  195.     LONG linenum = vw->vw_CursorPos.pos_Line;
  196.     LINE *line = vw->vw_Tx->tx_Lines + linenum;
  197.     LONG i = vw->vw_CursorPos.pos_Col - 1;
  198.     LONG (*cmpfunc)(STRPTR, STRPTR);
  199.  
  200.     if(WildSearch)
  201.     {
  202.     LONG prc;
  203.     if(CaseSearch)
  204.     {
  205.         prc = ParsePattern(SearchBuff, parsed, 202);
  206.         cmpfunc = MatchPattern;
  207.     }
  208.     else
  209.     {
  210.         prc = ParsePatternNoCase(SearchBuff, parsed, 202);
  211.         cmpfunc = MatchPatternNoCase;
  212.     }
  213.     if(prc < 0)
  214.     {
  215.         settitle("error: can't parse pattern for wildcard search");
  216.         return(FALSE);
  217.     }
  218.     find = parsed;
  219.     }
  220.     else
  221.     {
  222.     find = SearchBuff;
  223.     cmpfunc = CaseSearch ? mystrcmp : mystricmp;
  224.     }
  225.     while(linenum >= 0)
  226.     {
  227.     while(i >= 0)
  228.     {
  229.         if(cmpfunc(find, line->ln_Line + i))
  230.         {
  231.         setautomark();
  232.         vw->vw_CursorPos.pos_Col = i;
  233.         vw->vw_CursorPos.pos_Line = linenum;
  234.         return(TRUE);
  235.         }
  236.         i--;
  237.     }
  238.     line--;
  239.     linenum--;
  240.     i = line->ln_Strlen - 2;
  241.     }
  242.     settitlefmt("can't find %s", (LONG)SearchBuff);
  243.     return(FALSE);
  244. }
  245.  
  246. #ifndef NOREGEXP
  247. Local BOOL
  248. findREnext(VOID)
  249. {
  250.     VW *vw = CurrVW;
  251.     BOOL rc = FALSE;
  252.     if(vw->vw_LastRE.prog)
  253.     free(vw->vw_LastRE.prog);
  254.     if(vw->vw_LastRE.prog = regcomp(SearchBuff))
  255.     {
  256.     LONG linenum = vw->vw_CursorPos.pos_Line;
  257.     LINE *line = vw->vw_Tx->tx_Lines + linenum;
  258.     STRPTR tstr = line->ln_Line;
  259.     if(vw->vw_CursorPos.pos_Col >= line->ln_Strlen)
  260.         tstr += line->ln_Strlen;
  261.     else
  262.         tstr += vw->vw_CursorPos.pos_Col + 1;
  263.     if(*SearchBuff == '^')
  264.     {
  265.         line++;
  266.         linenum++;
  267.         tstr = line->ln_Line;
  268.     }
  269.     while(!rc && (vw->vw_Tx->tx_NumLines > linenum))
  270.     {
  271.         if(regexec(vw->vw_LastRE.prog, tstr))
  272.         rc = TRUE;
  273.         else
  274.         {
  275.         linenum++;
  276.         line++;
  277.         tstr = line->ln_Line;
  278.         }
  279.     }
  280.     if(rc)
  281.     {
  282.         vw->vw_CursorPos.pos_Line = linenum;
  283.         vw->vw_CursorPos.pos_Col = vw->vw_LastRE.prog->startp[0] - line->ln_Line;
  284.         vw->vw_LastRE.matchpos = vw->vw_CursorPos;
  285.         vw->vw_LastRE.changes = vw->vw_Tx->tx_Changes;
  286.     }
  287.     else
  288.     {
  289.         free(vw->vw_LastRE.prog);
  290.         vw->vw_LastRE.prog = NULL;
  291.         settitle("can't find match");
  292.     }
  293.     }
  294.     return(rc);
  295. }
  296.  
  297. Local BOOL
  298. findREprev(VOID)
  299. {
  300.     VW *vw = CurrVW;
  301.     BOOL rc = FALSE;
  302.     if(vw->vw_LastRE.prog)
  303.     free(vw->vw_LastRE.prog);
  304.     if(vw->vw_LastRE.prog = regcomp(SearchBuff))
  305.     {
  306.     LONG linenum = vw->vw_CursorPos.pos_Line;
  307.     LINE *line = vw->vw_Tx->tx_Lines + linenum;
  308.     STRPTR tstr = line->ln_Line;
  309.     if(vw->vw_CursorPos.pos_Col >= line->ln_Strlen)
  310.         tstr += line->ln_Strlen;
  311.     else
  312.         tstr += vw->vw_CursorPos.pos_Col + 1;
  313.     if(*SearchBuff == '^')
  314.     {
  315.         line--;
  316.         linenum--;
  317.         tstr = line->ln_Line;
  318.     }
  319.     while(!rc && (linenum > 0))
  320.     {
  321.         if(regexec(vw->vw_LastRE.prog, tstr))
  322.         rc = TRUE;
  323.         else
  324.         {
  325.         linenum--;
  326.         line--;
  327.         tstr = line->ln_Line;
  328.         }
  329.     }
  330.     if(rc)
  331.     {
  332.         vw->vw_CursorPos.pos_Line = linenum;
  333.         vw->vw_CursorPos.pos_Col = vw->vw_LastRE.prog->startp[0] - line->ln_Line;
  334.         vw->vw_LastRE.matchpos = vw->vw_CursorPos;
  335.         vw->vw_LastRE.changes = vw->vw_Tx->tx_Changes;
  336.     }
  337.     else
  338.     {
  339.         free(vw->vw_LastRE.prog);
  340.         vw->vw_LastRE.prog = NULL;
  341.         settitle("can't find match");
  342.     }
  343.     }
  344.     return(rc);
  345. }
  346. #endif /* NOREGEXP */
  347.  
  348. BOOL
  349. findcol0(STRPTR str)
  350. {
  351.     VW *vw = CurrVW;
  352.     TX *tx = vw->vw_Tx;
  353.     LINE *line = tx->tx_Lines;
  354.     LONG linenum = 0;
  355.  
  356.     while(linenum < tx->tx_NumLines)
  357.     {
  358.     if(mystrcmp(str, line->ln_Line))
  359.     {
  360.         setautomark();
  361.         vw->vw_CursorPos.pos_Col = 0;
  362.         vw->vw_CursorPos.pos_Line = linenum;
  363.         vw->vw_StartLine = linenum;
  364.         vw->vw_RefreshType |= RFF_ALL;
  365.         return(TRUE);
  366.     }
  367.     linenum++;
  368.     line++;
  369.     }
  370.     return(FALSE);
  371. }
  372.  
  373. Local BOOL
  374. replaceit(VOID)
  375. {
  376.     VW *vw = CurrVW;
  377.     LINE *line = vw->vw_Tx->tx_Lines + vw->vw_CursorPos.pos_Line;
  378.     WORD x = vw->vw_CursorPos.pos_Col;
  379.     BOOL rc = FALSE;
  380.     if((x < line->ln_Strlen) && (mystricmp(SearchBuff, line->ln_Line + x)))
  381.     {
  382.     WORD serlen = strlen(SearchBuff);
  383.     setrefresh(RFF_LINEFROM, x, vw->vw_CursorPos.pos_Line);
  384.     deletechars(strlen(SearchBuff));
  385.     rc = insertstr(ReplaceBuff);
  386.     vw->vw_Tx->tx_Changes++;
  387.     }
  388.     else
  389.     settitle("string under cursor doesn't match string in search buffer");
  390.     return(rc);
  391. }
  392.  
  393. #ifndef NOREGEXP
  394. Local BOOL
  395. replaceitRE(VOID)
  396. {
  397.     VW *vw = CurrVW;
  398.     BOOL rc = FALSE;
  399.     if(vw->vw_LastRE.prog)
  400.     {
  401.     if(vw->vw_LastRE.changes == vw->vw_Tx->tx_Changes)
  402.     {
  403.         if((vw->vw_CursorPos.pos_Line == vw->vw_LastRE.matchpos.pos_Line) && (vw->vw_CursorPos.pos_Col == vw->vw_LastRE.matchpos.pos_Col))
  404.         {
  405.         LONG replen = regsublen(vw->vw_LastRE.prog, ReplaceBuff);
  406.         STRPTR repstr;
  407.         setrefresh(RFF_LINEFROM, vw->vw_CursorPos.pos_Col, vw->vw_CursorPos.pos_Line);
  408.         deletechars(vw->vw_LastRE.prog->endp[0] - vw->vw_LastRE.prog->startp[0]);
  409.         if(replen && (repstr = AllocVec(replen, 0)))
  410.         {
  411.             regsub(vw->vw_LastRE.prog, ReplaceBuff, repstr);
  412.             rc = insertstr(repstr);
  413.             FreeVec(repstr);
  414.         }
  415.         else if(replen)
  416.             settitle(NoMemMsg);
  417.         vw->vw_Tx->tx_Changes++;
  418.         }
  419.         else
  420.         settitle("error: cursor not at match position");
  421.     }
  422.     else
  423.     {
  424.         free(vw->vw_LastRE.prog);
  425.         vw->vw_LastRE.prog = NULL;
  426.         settitle("error: file has changed since last RE match");
  427.     }
  428.     }
  429.     else
  430.     settitle("error: must match the RE before replacing it");
  431.     return(rc);
  432. }
  433.  
  434. void
  435. regerror(char *err)
  436. {
  437.     settitle(err);
  438. }
  439. #endif /* NOREGEXP */
  440.  
  441. /*
  442.  * These functions return TRUE if the strings match, if str1 ends before
  443.  * str2 they are still considered to be matching.
  444.  */
  445. Local BOOL
  446. mystrcmp(STRPTR str1, STRPTR str2)
  447. {
  448.     while(*str1 && (*str1 == *str2++))
  449.     str1++;
  450.     if(!(*str1))
  451.     return(TRUE);
  452.     return(FALSE);
  453. }
  454.  
  455. Local BOOL
  456. mystricmp(STRPTR str1, STRPTR str2)
  457. {
  458.     while(*str1 && ((toupper(*str1) == toupper(*str2++))))
  459.     str1++;
  460.     if(!(*str1))
  461.     return(TRUE);
  462.     return(FALSE);
  463. }
  464.